import json  # 导入json模块，用于处理JSON格式数据
import time  # 导入time模块，用于时间相关操作
import threading  # 导入threading模块，用于多线程操作

from hqyj_mqtt import Mqtt_Clt  # 从自定义的hqyj_mqtt模块导入Mqtt_Clt类，用于MQTT通信
import base64  # 导入base64模块，用于Base64编码和解码
import numpy as np  # 导入numpy库并简写为np，用于数值计算和数组操作
import cv2  # 导入OpenCV库，用于图像处理
from predict import predict_resnet  # 从predict模块导入predict_resnet函数，用于图像识别

# 定义光推杆序号常量，提高代码可读性，避免后续编程时混淆
load_rod = "first"  # 加载推杆
ripe_rod = "second"  # 成熟果实推杆
half_ripe_rod = "third"  # 半成熟果实推杆
raw_rod = "fourth"  # 生果实推杆
all_rod = "all"  # 所有推杆

# 定义光电对管状态字典，初始值均为False（未触发）
ripe_switch = {"first_switch": False}  # 成熟果实对应的光电对管
half_ripe_switch = {"second_switch": False}  # 半成熟果实对应的光电对管
raw_switch = {"third_switch": False}  # 生果实对应的光电对管


def push_pull(rod):
    """控制推杆先推出再收回的函数"""
    # 发送JSON消息控制推杆推出
    mqtt_client.send_json_msg(json.dumps({"rod_control": f"{rod}_push"}))
    time.sleep(0.5)  # 等待0.5秒，确保推杆完全推出
    # 发送JSON消息控制推杆收回
    mqtt_client.send_json_msg(json.dumps({"rod_control": f"{rod}_pull"}))


if __name__ == '__main__':
    # 创建MQTT客户端实例，连接到本地服务器，参数包括地址、端口、用户名、密码和超时时间
    mqtt_client = Mqtt_Clt("127.0.0.1", 21883, "bb", "aa", 60)
    print("开始控制")
    # 控制传送带开始运行
    mqtt_client.control_device("conveyor", 'run')

    # 控制所有推杆收回初始位置
    mqtt_client.control_device("rod_control", "all_pull")
    # 0.5秒后启动加载推杆的推-拉动作（使用定时器线程，不阻塞主程序）
    threading.Timer(0.5, push_pull, args=(load_rod,)).start()

    result = None  # 初始化识别结果变量
    while True:  # 进入无限循环，持续处理消息
        msg = mqtt_client.mqtt_queue.get()  # 从MQTT消息队列获取消息

        # 如果获取的是图像数据
        if 'image' in msg:
            # 将Base64编码的字符串解码为原始二进制数据
            image_data = base64.b64decode(msg['image'])
            # 将二进制数据转换为np.uint8类型的NumPy数组
            image_array = np.frombuffer(image_data, np.uint8)
            # 将NumPy数组解码为OpenCV图像对象（彩色图像）
            image = cv2.imdecode(image_array, cv2.IMREAD_COLOR)
            # 使用ResNet模型进行图像识别，获取结果
            result = predict_resnet(image)
            print(f"result: {result}")  # 打印识别结果

        # 如果不是图像数据，处理其他控制消息
        else:
            # 根据识别结果和光电对管状态，控制相应的推杆动作
            # 当识别为成熟果实且对应的光电对管被触发时
            if (result == "ripe") and (ripe_switch == msg):
                # 立即启动成熟果实推杆的推-拉动作
                threading.Timer(0.0, push_pull, args=(ripe_rod,)).start()
                # 0.2秒后启动加载推杆的推-拉动作
                threading.Timer(0.2, push_pull, args=(load_rod,)).start()
            # 当识别为半成熟果实且对应的光电对管被触发时
            elif (result == "half-ripe") and (half_ripe_switch == msg):
                # 立即启动半成熟果实推杆的推-拉动作
                threading.Timer(0.0, push_pull, args=(half_ripe_rod,)).start()
                # 0.2秒后启动加载推杆的推-拉动作
                threading.Timer(0.2, push_pull, args=(load_rod,)).start()
            # 当识别为生果实且对应的光电对管被触发时
            elif (result == "raw") and (raw_switch == msg):
                # 立即启动生果实推杆的推-拉动作
                threading.Timer(0.0, push_pull, args=(raw_rod,)).start()
                # 0.2秒后启动加载推杆的推-拉动作
                threading.Timer(0.2, push_pull, args=(load_rod,)).start()